package com.cirnoworks.uhs;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.LinkedHashMap;
import java.util.Map.Entry;

public class AddressCache {

	private static final LinkedHashMap<AddressKey, InetSocketAddress> cache = new LinkedHashMap<AddressKey, InetSocketAddress>() {

		@Override
		protected boolean removeEldestEntry(
				Entry<AddressKey, InetSocketAddress> eldest) {
			return size() > 10000;
		}

	};

	public static void getAddress(InetSocketAddress address, AddressKey output) {
		long addr = 0;
		for (byte b : address.getAddress().getAddress()) {
			addr = (addr << 8) | (b & 0xff);
		}
		output.setAddress(addr);
		output.setPort(address.getPort());
		if (!cache.containsKey(output)) {
			cache.put(output.clone(), address);
		}
	}

	public static InetSocketAddress getAddress(AddressKey key) {
		InetSocketAddress ret = cache.get(key);
		if (ret == null) {
			long addr = key.getAddress();
			byte[] add;
			if (addr >>> 32 == 0) {
				// v4
				add = new byte[4];
				for (int i = 3; i >= 0; i--) {
					add[i] = (byte) addr;
					addr >>= 8;
				}
			} else {
				// v6
				add = new byte[8];
				for (int i = 7; i >= 0; i--) {
					add[i] = (byte) addr;
					addr >>= 8;
				}
			}
			try {
				ret = new InetSocketAddress(InetAddress.getByAddress(add),
						key.getPort());
			} catch (UnknownHostException e) {
				throw new RuntimeException(e);
			}
			cache.put(key.clone(), ret);
		}
		return ret;
	}
}
